Linux kernel lesson
查看/设置硬件信息和配置
查看硬件信息收集指令:
lshw和lspcilsusb和lsblklscpu和lsdev
指令前需要加上sudo
硬件控制和配置指令:
hdparm:获取或设置硬盘参数inb和outb:访问PC硬件上的IO端口setpci:配置PCI设备
问题:如何查看Linux系统以下问题?
系统上有没有PCI Ethernet设备?
lspci | grep -i 'ethernet'系统上有多少CPU?
lscpu | grep '^CPU'系统上有多少块设备?
lsblk | wc -l
系统调用
- 可以通过
strace追踪进程系统调用,使用-p选项追加进程号,可查看对应运行进程当前的系统调用情况
问题:
使用 man 命令,确定 strace 的哪个选项将显示进程调用每个系统调用的次数的摘要和计数;使用该选项,截至命令date调用最多的系统调用是什么?
strace -c date # 可以看到系统调用date的次数和计数
strace -c -S calls date # 可以按照calls列来进行从大到小的排序你能用 strace 确定哪个系统调用用于更改目录吗?
由于cd并不是linux内置的指令,实际上是shell内置的指令,我们可以通过
whereis cd发现没有具体路径:zjp@zjp-virtual-machine:~$ whereis cd
cd:我们可以编写一个简单的测试脚本,并使用
strace的-f选项来追踪bash在执行cd的时候做了哪些操作:echo "cd /noexit" > cd_test.sh # cd到一个不存在的文件目录
chmod +x cd_test.sh
strace -f bash ./cd_test.sh
strace -f bash ./cd_test.sh |& grep -i "noexit"
# 输出如下
read(255, "cd /noexit\n", 11) = 11
newfstatat(AT_FDCWD, "/noexit", 0x7ffe70730b10, 0) = -1 ENOENT (没有那个文件或目录)
chdir("/noexit") = -1 ENOENT (没有那个文件或目录)
chdir("/noexit") = -1 ENOENT (没有那个文件或目录)
write(2, "./cd_test.sh: \347\254\254 1 \350\241\214\357\274\232 cd: /"..., 68./cd_test.sh: 第 1 行: cd: /noexit: 没有那个文件或目录编写一个单行 shell 脚本,其中内容为 date > /dev/null,然后使用 strace 的 -f 选项跟踪新进程,并使用 -o 将 trace 输出放入文件中,以确定 date 命令是否是打开 /dev/null 的进程
# 编写脚本并赋予执行权限
echo "date > /dev/null" > test_date.sh && chmod +x test_date.sh
strace -f -o output.out bash ./test_date.sh
cat output.out |& grep -i "date"
# 输出如下
214001 execve("/usr/bin/bash", ["bash", "./test_date.sh"], 0x7ffc350f04b0 /* 25 vars */) = 0
214001 openat(AT_FDCWD, "./test_date.sh", O_RDONLY) = 3
214001 newfstatat(AT_FDCWD, "./test_date.sh", {st_mode=S_IFREG|0775, st_size=17, ...}, 0) = 0
214001 read(3, "date > /dev/null\n", 80) = 17
214001 read(255, "date > /dev/null\n", 17) = 17
214001 newfstatat(AT_FDCWD, "/usr/local/sbin/date", 0x7ffe85d5aa80, 0) = -1 ENOENT (没有那个文件或目录)
214001 newfstatat(AT_FDCWD, "/usr/local/bin/date", 0x7ffe85d5aa80, 0) = -1 ENOENT (没有那个文件或目录)
214001 newfstatat(AT_FDCWD, "/usr/sbin/date", 0x7ffe85d5aa80, 0) = -1 ENOENT (没有那个文件或目录)
214001 newfstatat(AT_FDCWD, "/usr/bin/date", {st_mode=S_IFREG|0755, st_size=104968, ...}, 0) = 0
214001 newfstatat(AT_FDCWD, "/usr/bin/date", {st_mode=S_IFREG|0755, st_size=104968, ...}, 0) = 0
214001 access("/usr/bin/date", X_OK) = 0
214001 newfstatat(AT_FDCWD, "/usr/bin/date", {st_mode=S_IFREG|0755, st_size=104968, ...}, 0) = 0
214001 access("/usr/bin/date", R_OK) = 0
214001 newfstatat(AT_FDCWD, "/usr/bin/date", {st_mode=S_IFREG|0755, st_size=104968, ...}, 0) = 0
214001 newfstatat(AT_FDCWD, "/usr/bin/date", {st_mode=S_IFREG|0755, st_size=104968, ...}, 0) = 0
214001 access("/usr/bin/date", X_OK) = 0
214001 newfstatat(AT_FDCWD, "/usr/bin/date", {st_mode=S_IFREG|0755, st_size=104968, ...}, 0) = 0
214001 access("/usr/bin/date", R_OK) = 0
214008 execve("/usr/bin/date", ["date"], 0x5a3cfce71f70 /* 25 vars */) = 0
内核信息和/proc
问题:
你能找到内核命令行的proc文件吗?
cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.0-65-generic root=UUID=23d3faea-ccb5-45c3-be38-1ed1adebaa00 ro quiet splash使用
dmesg和grep,你是否看到内核报告了内核命令行?
- 如果没有,你能确定内核的启动消息是否丢失了吗?
- 你的系统是否有记录启动消息的日志文件? 你可以在
/var/log下使用grep搜索BOOT_IMAGE来查看。sudo dmesg | grep BOOT_IMAGE
# jounalctl 检索systemd日志 -k(--demesg)仅显示内核日志
journalctl -k | grep BOOT_IMAGE
grep -r BOOT_IMAGE /var/log根据
/proc/meminfo,你的系统总共有多少RAM?head /proc/meminfo
MemTotal: 3961432 kB
MemFree: 112504 kB
MemAvailable: 2282668 kB
Buffers: 46112 kB
Cached: 2275048 kB
SwapCached: 6664 kB
Active: 1002672 kB
Inactive: 2191320 kB
Active(anon): 529920 kB
Inactive(anon): 369024 kB
/sys
sysfs文件系统会在boot的时候挂载到/syssysfs表示内核对象信息(硬件信息,如PCI驱动信息)/sys/kernel/debugfs/sys/kernel/tracing/sys/module内核可加载模块信息
问题:
lspci从哪些文件获取信息? 使用strace-e openatlspci查看# 打开了/sys/bus/devices下的设备文件
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:00.0/vendor", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:00.0/device", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:00.0/class", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:17.1/config", O_RDONLY) = 3
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:17.1/vendor", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:17.1/device", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:17.1/class", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:0f.0/config", O_RDONLY) = 3
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:0f.0/vendor", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:0f.0/device", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:0f.0/class", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:15.4/config", O_RDONLY) = 3
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:15.4/vendor", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:15.4/device", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:15.4/class", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:18.6/config", O_RDONLY) = 3
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:18.6/vendor", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:18.6/device", O_RDONLY) = 4
openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:18.6/class", O_RDONLY) = 4
- 根据
/sys/block,你有块设备(磁盘)sda吗?如果有,你有sda分区的设备文件吗?有多少个?cd /sys/block/ && ls -l sda*
lrwxrwxrwx 1 root root 0 8月 18 11:23 sda -> ../devices/pci0000:00/0000:00:10.0/host32/target32:0:0/32:0:0:0/block/sda
- 使用strace,命令
fdisk-l(以root权限运行)是否打开了/sys/block下的任何文件?/sys/dev/block呢?sudo strace -e openat -o strace_fdisk.out fdisk -l
# 由于只有一个sda文件,所以在block下面其他sda打开失败了
grep "/sys/block/sda" strace_fdisk.out
openat(AT_FDCWD, "/sys/block/sda/dev", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/sys/block/sda1/dev", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/sys/block/sda1/device/dev", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/sys/block/sda2/dev", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/sys/block/sda2/device/dev", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/sys/block/sda3/dev", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/sys/block/sda3/device/dev", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
# 还打开了/sys/dev下的很多文件
grep "/sys/dev" strace_fdisk.out
openat(AT_FDCWD, "/sys/dev/block/7:0", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/sys/dev/block/7:0", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/sys/dev/block/7:0", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/sys/dev/block/7:0", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/sys/dev/block/7:0", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/sys/dev/block/7:0", O_RDONLY|O_CLOEXEC) = 5